package async.callback;

import cn.hutool.core.thread.ThreadUtil;
import com.alibaba.fastjson.JSONObject;
import com.google.common.base.Stopwatch;
import common.model.Member;
import common.model.Order;
import org.junit.Before;
import org.junit.Test;
import org.springframework.util.StopWatch;

import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collector;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @author jiangwz
 * @create 2020/10/22.
 */
public class CompletableFutureTests {

    private MockService mockService;

    @Before
    public void before(){
        mockService = new MockService();
    }


    @Test
    public void test01() throws ExecutionException, InterruptedException {

        // Create a CompletableFuture
        CompletableFuture<String> whatsYourNameFuture = CompletableFuture.supplyAsync(() -> {
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                throw new IllegalStateException(e);
            }
            return "Rajeev";
        });

        CompletableFuture<String> greetingFuture = whatsYourNameFuture.thenApply(name -> {
            return "Hello " + name;
        });

        CompletableFuture<JSONObject> apply = greetingFuture.thenApply(name -> {
            JSONObject json = new JSONObject();
            json.put("name", name);
            return json;
        });

//        System.out.println("end");
//        System.out.println(greetingFuture.get()); // Hello Rajeev

//        System.out.println(apply.get());
        apply.whenComplete((res, e) -> {
            System.out.println(res);
        });
        System.out.println("end");
        ThreadUtil.safeSleep(4000);
    }

    @Test
    public void test02() throws ExecutionException, InterruptedException {
        CompletableFuture<String> welcomeText = CompletableFuture.supplyAsync(() -> {
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                throw new IllegalStateException(e);
            }
            return "Rajeev";
        }).thenApply(name -> {
            return "Hello " + name;
        }).thenApply(greeting -> {
            return greeting + ", Welcome to the CalliCoder Blog";
        });

        System.out.println("end");
        System.out.println(welcomeText.get());
// Prints - Hello Rajeev, Welcome to the CalliCoder Blog
    }


    @Test
    public void test03(){

        CompletableFuture<Integer> future
                = CompletableFuture.supplyAsync(() -> 0);

        future.thenApplyAsync(x -> x + 1) // call 1
                .thenApplyAsync(x -> x + 1)
                .thenAccept(x -> System.out.println(Thread.currentThread().getName()+" async result: " + x));

        future.thenApply(x -> x + 1) // call 2
                .thenApply(x -> x + 1)
                .thenAccept(x -> System.out.println(Thread.currentThread().getName()+" sync result:" + x));
    }

    @Test
    public void test04() throws ExecutionException, InterruptedException {


        CompletableFuture<Object> future
                = CompletableFuture.supplyAsync(() -> 0);
        CompletableFuture<Void> future1
                = CompletableFuture.supplyAsync(() -> {
            try {
                 TimeUnit.SECONDS.sleep(5);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return null;
        });

        CompletableFuture.allOf(future, future1).join();

//        String className = future.get().getClass().getName();
//        Class.forName(className)

    }

    /**
     * 异步流式处理
     * @throws ExecutionException
     * @throws InterruptedException
     */
    @Test
    public void test05() throws ExecutionException, InterruptedException {
        CompletableFuture<JSONObject> apply = CompletableFuture.supplyAsync(() -> {
            try {
                TimeUnit.SECONDS.sleep(5);
            } catch (InterruptedException e) {
                throw new IllegalStateException(e);
            }
            return "Rajeev";
        }).thenApply(name -> {
            return "Hello " + name;
        }).thenApply(name -> {
            JSONObject json = new JSONObject();
            json.put("name", name);
            return json;
        });
        System.out.println(apply.get());
    }

    @Test
    public void test06() throws ExecutionException, InterruptedException {
        CompletableFuture<String> async = CompletableFuture.supplyAsync(() -> {
            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "hello";
        }).whenCompleteAsync((val, e) -> {
            // 由于是biConsumer,所以只能做action操作,不能有返回值
            System.out.println("执行完毕");
        });
        System.out.println(async.get());

    }

    @Test
    public void test07(){
        Stopwatch started = Stopwatch.createStarted();
        CompletableFuture<List<Member>> membersFuture = CompletableFuture.supplyAsync(() -> mockService.getMemberList());
        CompletableFuture<List<Order>> ordersFuture = CompletableFuture.supplyAsync(() -> mockService.getOrderList());
        CompletableFuture.allOf(membersFuture, ordersFuture).join();
        started.stop();
        //3.722 s
        System.out.println(started.toString());




    }

    @Test
    public void test08(){
        Stopwatch started = Stopwatch.createStarted();
        mockService.getMemberList();
        mockService.getOrderList();
        started.stop();
        //4.524 s
        System.out.println(started.toString());

    }
}
